﻿-- Author      : Kurapica
-- Create Date : 8/03/2008 17:14

--------------------------
-- MultiLineTextBox     --
--------------------------
do
	-- Check Version
	local version = 1

	if not IGAS:RegisterFile("IGAS.GUI.Widget.MultiLineTextBox", version) then
		return
	end
		
    local getmetatable = getmetatable
    local pairs = pairs
    local ipairs = ipairs
    local type = type
    local error = error
	local strsub = strsub
    local CreateFrame = IGAS.GUI.CreateFrame
    
	local _WidgetName = "MultiLineTextBox"
    local _Base = "Frame"

	local _GUI = IGAS.GUI
	local _Widget = IGAS.GUI.Widget
    local _BaseFunc = IGAS.GUI.Base.Func
	local _PropertyType = IGAS.GUI.Base.PropertyType
	
    -- Scripts
    local _FrameBackdrop = {
        bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 16,
        insets = { left = 3, right = 3, top = 3, bottom = 3 }
    }
    
    local function OnScrollRangeChanged(self, scrollrange)
        local scrollbar = self:GetChild("Bar")
        
        if ( not scrollrange or scrollrange == 0) then
            scrollrange = self:GetVerticalScrollRange()
        end
        
        local value = scrollbar:GetValue()
        if ( value > scrollrange ) then
            value = scrollrange;
        end
        
        scrollbar:SetMinMaxValues(0, scrollrange)
        scrollbar:SetValue(value)
        
        if ( floor(scrollrange) == 0 ) then
            scrollbar:Disable()
        else
            scrollbar:Enable()
        end
    end
    
    local function OnMouseWheel(self, delta)
        local scrollBar = self:GetChild("Bar")
        if ( delta > 0 ) then
            --scrollBar:SetValue(scrollBar:GetValue() - (scrollBar:GetHeight() / 2))
            scrollBar:SetValue(scrollBar:GetValue() - 20)
        else
            --scrollBar:SetValue(scrollBar:GetValue() + (scrollBar:GetHeight() / 2))
            scrollBar:SetValue(scrollBar:GetValue() + 20)
        end
    end
    
    local function OnSizeChanged(self)
        --self:GetChild("Bar").ValueStep = self.Height / 2
        self:GetChild("Container").Height = self.Height
        self:GetChild("Container").Width = self.Width - 16
        self:GetChild("Container"):GetChild("Text").Width = self.Width - 16
    end
    
    local function OnVerticalScroll(self, offset)
        self:GetChild("Bar").Value = offset
    end
    
    local function OnCursorChanged(self, x, y, w, h)
        self.cursorOffset = y
        self.cursorHeight = h
    end
    
    local function OnUpdate(self, elapsed)
        local height, range, scroll, size, cursorOffset, scrollFrame
        
        if (self.cursorOffset) then
            scrollFrame = self:GetParent():GetParent()
            height = scrollFrame:GetHeight();
            range = scrollFrame:GetVerticalScrollRange();
            scroll = scrollFrame:GetVerticalScroll();
            size = height + range;
            cursorOffset = -self.cursorOffset;
            
            if ( math.floor(height) <= 0 or math.floor(range) <= 0 ) then
                --Frame has no area, nothing to calculate.
                return;
            end
            
            while ( cursorOffset < scroll ) do
                scroll = (scroll - (height / 2));
                if ( scroll < 0 ) then
                    scroll = 0;
                end
                scrollFrame:SetVerticalScroll(scroll);
            end
    
            while ( (cursorOffset + self.cursorHeight) > (scroll + height) and scroll < range ) do
                scroll = (scroll + (height / 2));
                if ( scroll > range ) then
                    scroll = range;
                end
                scrollFrame:SetVerticalScroll(scroll);
            end
            
            self.cursorOffset = nil;
        end
    end
    
    local function OnMouseUp(self)
        self:GetChild("Container"):GetChild("Text"):SetFocus()
    end
    
    local function OnEscapePressed(self)
        self:ClearFocus()
    end
    
    local function OnTextChanged(self)
		self:GetParent():GetParent():UpdateScrollChildRect()
		local value = self:GetText()
		if value ~= self.__lasttext then
            self.__Container:Fire("OnTextChanged", value)
            self.__lasttext = value
		end
	end
  
	-- ScriptType
	local _ScriptType = {
        ["OnTextChanged"] = true,
    }
	    
	--	FuncProxy
	local _FuncProxy = {
    }
	
	--	Property
	local _Property = {
        -- Text
        ["Text"] = {
			["Set"] = function(self, text)
                self.__Text.__lasttext = text
				self.__Text.Text = text
			end,
			
			["Get"] = function(self)
				return self.__Text.Text
			end,
			
			["Type"] = _PropertyType.String,
        },
    
        -- AutoFocus
        ["AutoFocus"] = {
			["Set"] = function(self, state)
				self.__Text.AutoFocus = state
			end,
			
			["Get"] = function(self)
				return self.__Text.AutoFocus
			end,
			
			["Type"] = _PropertyType.Boolean,
		},    
        
        -- Focus
        ["Focused"] = {
			["Set"] = function(self, focus)
                self.__Text.Focused = focus
			end,
			
			["Get"] = function(self)
				return self.__Text.Focused
			end,
			
			["Type"] = _PropertyType.Boolean,
		},    
        
        -- AltArrowKeyMode
        ["AltArrowKeyMode"] = {
			["Set"] = function(self, enable)
                self.__Text.AltArrowKeyMode = enable
			end,
			
			["Get"] = function(self)
				return self.__Text.AltArrowKeyMode
			end,
			
			["Type"] = _PropertyType.Boolean,
		},    
    
        -- BlinkSpeed
        ["BlinkSpeed"] = {
			["Set"] = function(self, speed)
				self.__Text.BlinkSpeed = speed
			end,
			
			["Get"] = function(self)
				return self.__Text.BlinkSpeed
			end,
			
			["Type"] = _PropertyType.Number,
		},
    
        -- CursorPosition
        ["CursorPosition"] = {
			["Set"] = function(self, position)
				self.__Text.CursorPosition = position
			end,
			
			["Get"] = function(self)
				return self.__Text.CursorPosition
			end,
			
			["Type"] = _PropertyType.Number,
		},
    
        -- MaxBytes
        ["MaxBytes"] = {
			["Set"] = function(self, maxBytes)
				self.__Text.MaxBytes = maxBytes
			end,
			
			["Get"] = function(self)
				return self.__Text.MaxBytes
			end,
			
			["Type"] = _PropertyType.Number,
		},
    }
	
    -- Scripts        
    local function _New(parent)
        local back = CreateFrame("Frame", nil, parent)
        back.MouseWheelEnabled = true
		back.MouseEnabled = true
        
		back:SetBackdrop(_FrameBackdrop)
		back:SetBackdropColor(0, 0, 0)
        back:SetBackdropColor(0, 0, 0, 1)
		--back:SetBackdropBorderColor(0.4, 0.4, 0.4)
        
		local frame = CreateFrame("ScrollFrame","ScrollFrame",back)
        frame:SetPoint("TOPLEFT", back, "TOPLEFT", 5, -6)
		frame:SetPoint("BOTTOMRIGHT", back, "BOTTOMRIGHT", -5, 6)
        frame.MouseWheelEnabled = true
		frame.MouseEnabled = true
        
        local slider = CreateFrame("ScrollBar", "Bar", frame)
        slider:SetMinMaxValues(0,0)
        slider.Value = 0
        slider.ValueStep = 1
        
        local container = CreateFrame("Frame", "Container", frame)
        frame:SetScrollChild(container)
		container:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
		container:SetPoint("TOPRIGHT",slider,"TOPLEFT",0,0)
        container.Height = 20

		local editbox = CreateFrame("EditBox", "Text", container)
		editbox:SetPoint("TOPLEFT", container, "TOPLEFT", 0,0)
		editbox.Height = container.Height
		editbox.Width = container.Width
		editbox:SetMultiLine(true)
		editbox:SetTextInsets(5, 5, 3, 3)
		editbox:EnableMouse(true)
		editbox:SetAutoFocus(false)
		editbox:SetFontObject(ChatFontNormal)
        
        back.__Text = editbox
        editbox.__Container = back
		        
		frame.OnMouseUp = OnMouseUp
        frame.OnScrollRangeChanged = OnScrollRangeChanged
        frame.OnSizeChanged = OnSizeChanged
        frame.OnShow = OnSizeChanged
        frame.OnMouseWheel = OnMouseWheel
        frame.OnVerticalScroll = OnVerticalScroll

		editbox.OnEscapePressed = OnEscapePressed
		editbox.OnTextChanged = OnTextChanged
	    editbox.OnCursorChanged = OnCursorChanged
        editbox.OnUpdate = OnUpdate
        
		return back
	end
	
	-- Register
    local _WidgetInfo = {
        ["WidgetName"] = _WidgetName,
        ["Base"] = _Base,
        ["FuncProxy"] = _FuncProxy,
        ["Property"] = _Property,
        ["ScriptType"] = _ScriptType,
        ["New"] = _New,
    }
    
    _Widget[_WidgetName] = _GUI.NewWidget(_WidgetInfo)
end
